return serial;
}
+guint32
+broadway_output_grab_pointer (BroadwayOutput *output,
+ int id,
+ gboolean owner_event,
+ guint32 time_)
+{
+ char buf[HEADER_LEN + 3 + 1 + 6];
+ guint32 serial;
+ int p;
+
+ serial = output->serial;
+ p = write_header (output, buf, 'g');
+ append_uint16 (id, buf, &p);
+ buf[p++] = owner_event ? '1': '0';
+ append_uint32 (time_, buf, &p);
+
+ assert (p == sizeof (buf));
+
+ broadway_output_write (output, buf, sizeof (buf));
+
+ return serial;
+}
+
+guint32
+broadway_output_ungrab_pointer (BroadwayOutput *output,
+ guint32 time_)
+{
+ char buf[HEADER_LEN + 6];
+ guint32 serial;
+ int p;
+
+ serial = output->serial;
+ p = write_header (output, buf, 'u');
+ append_uint32 (time_, buf, &p);
+
+ assert (p == sizeof (buf));
+
+ broadway_output_write (output, buf, sizeof (buf));
+
+ return serial;
+}
+
void
broadway_output_new_surface(BroadwayOutput *output, int id, int x, int y, int w, int h)
{
return null;
}
+var grab = new Object();
+grab.window = null;
+grab.owner_events = false;
+grab.time = 0;
+grab.implicit = false;
var last_serial = 0;
var last_x = 0;
var last_y = 0;
+var real_window_with_mouse = 0;
var window_with_mouse = 0;
var surfaces = {};
var outstanding_commands = new Array();
return context;
}
+var GDK_GRAB_SUCCESS = 0;
+var GDK_GRAB_ALREADY_GRABBED = 1;
+var GDK_GRAB_INVALID_TIME = 2;
+
+var GDK_CROSSING_NORMAL = 0;
+var GDK_CROSSING_GRAB = 1;
+var GDK_CROSSING_UNGRAB = 2;
+
function handleCommands(cmd_obj)
{
var cmd = cmd_obj.data;
send_input ("q", [pos.root_x, pos.root_y, pos.win_x, pos.win_x, window_with_mouse]);
break;
+ case 'g': // Grab
+ var id = base64_16(cmd, i);
+ i = i + 3;
+ var owner_events = cmd[i++] == '1';
+ var time = base64_32(cmd, i);
+ i = i + 6;
+
+ if (grab.window != null) {
+ /* Previous grab, compare times */
+ if (time != 0 && grab.time != 0 &&
+ time > grab.time) {
+ send_input ("g", [GDK_GRAB_INVALID_TIME]);
+ break;
+ }
+ }
+
+ doGrab(id, owner_events, time, false);
+
+ send_input ("g", [GDK_GRAB_SUCCESS]);
+
+ break;
+
+ case 'u': // Ungrab
+ var time = base64_32(cmd, i);
+ i = i + 6;
+ send_input ("u", []);
+
+ if (grab.window != null) {
+ if (grab.time == 0 || time == 0 ||
+ grab.time < time)
+ grab.window = null;
+ }
+
+ break;
default:
alert("Unknown op " + command);
}
return res;
}
+function getEffectiveEventTarget (id) {
+ if (grab.window != null) {
+ if (!grab.owner_events)
+ return grab.window;
+ if (id == 0)
+ return grab.window;
+ }
+ return id;
+}
+
function on_mouse_move (ev) {
var id = get_surface_id(ev);
+ id = getEffectiveEventTarget (id);
var pos = getPositionsFromEvent(ev, id);
send_input ("m", [id, pos.root_x, pos.root_y, pos.win_x, pos.win_y, ev.timeStamp]);
}
function on_mouse_over (ev) {
var id = get_surface_id(ev);
+ real_window_with_mouse = id;
+ id = getEffectiveEventTarget (id);
var pos = getPositionsFromEvent(ev, id);
window_with_mouse = id;
if (window_with_mouse != 0) {
- send_input ("e", [id, pos.root_x, pos.root_y, pos.win_x, pos.win_y, ev.timeStamp]);
+ send_input ("e", [id, pos.root_x, pos.root_y, pos.win_x, pos.win_y, ev.timeStamp, GDK_CROSSING_NORMAL]);
}
}
function on_mouse_out (ev) {
var id = get_surface_id(ev);
+ var origId = id;
+ id = getEffectiveEventTarget (id);
var pos = getPositionsFromEvent(ev, id);
if (id != 0) {
- send_input ("l", [id, pos.root_x, pos.root_y, pos.win_x, pos.win_y, ev.timeStamp]);
+ send_input ("l", [id, pos.root_x, pos.root_y, pos.win_x, pos.win_y, ev.timeStamp, GDK_CROSSING_NORMAL]);
}
+ real_window_with_mouse = 0;
window_with_mouse = 0;
}
+function doGrab(id, owner_events, time, implicit) {
+ var pos;
+
+ if (window_with_mouse != id) {
+ if (window_with_mouse != 0) {
+ pos = getPositionsFromAbsCoord(last_x, last_y, window_with_mouse);
+ send_input ("l", [window_with_mouse, pos.root_x, pos.root_y, pos.win_x, pos.win_y, time, GDK_CROSSING_GRAB]);
+ }
+ pos = getPositionsFromAbsCoord(last_x, last_y, id);
+ send_input ("e", [id, pos.root_x, pos.root_y, pos.win_x, pos.win_y, time, GDK_CROSSING_GRAB]);
+ window_with_mouse = id;
+ }
+
+ grab.window = id;
+ grab.owner_events = owner_events;
+ grab.time = time;
+ grab.implicit = implicit;
+}
+
+function doUngrab() {
+ var pos;
+ if (real_window_with_mouse != window_with_mouse) {
+ if (window_with_mouse != 0) {
+ pos = getPositionsFromAbsCoord(last_x, last_y, window_with_mouse);
+ send_input ("l", [window_with_mouse, pos.root_x, pos.root_y, pos.win_x, pos.win_y, ev.timeStamp, GDK_CROSSING_UNGRAB]);
+ }
+ if (real_window_with_mouse != 0) {
+ pos = getPositionsFromAbsCoord(last_x, last_y, id);
+ send_input ("e", [real_window_with_mouse, pos.root_x, pos.root_y, pos.win_x, pos.win_y, ev.timeStamp, GDK_CROSSING_UNGRAB]);
+ }
+ window_with_mouse = real_window_with_mouse;
+ }
+ grab.window = null;
+}
+
function on_mouse_down (ev) {
var id = get_surface_id(ev);
+ id = getEffectiveEventTarget (id);
var pos = getPositionsFromEvent(ev, id);
+ if (grab.window != null)
+ doGrab (id, false, ev.timeStamp, true);
send_input ("b", [id, pos.root_x, pos.root_y, pos.win_x, pos.win_y, ev.timeStamp, ev.button]);
}
function on_mouse_up (ev) {
var id = get_surface_id(ev);
+ id = getEffectiveEventTarget (id);
var pos = getPositionsFromEvent(ev, id);
send_input ("B", [id, pos.root_x, pos.root_y, pos.win_x, pos.win_y, ev.timeStamp, ev.button]);
+
+ if (grab.window != null && grab.implicit)
+ doUngrab();
}
var last_key_down = 0;
serial = broadway_output_query_pointer (broadway_display->output, impl->id);
- reply = _gdk_broadway_display_block_for_input (display, 'q', serial);
+ reply = _gdk_broadway_display_block_for_input (display, 'q', serial, TRUE);
if (reply != NULL)
{
GdkCursor *cursor,
guint32 time_)
{
- return GDK_GRAB_NOT_VIEWABLE;
+ GdkDisplay *display;
+ GdkBroadwayDisplay *broadway_display;
+ GdkWindowImplBroadway *impl;
+ guint32 serial;
+ char *reply;
+
+ display = gdk_device_get_display (device);
+ broadway_display = GDK_BROADWAY_DISPLAY (display);
+
+ if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
+ {
+ /* Device is a keyboard */
+ return GDK_GRAB_SUCCESS;
+ }
+ else
+ {
+ /* Device is a pointer */
+
+ if (broadway_display->output)
+ {
+ impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
+
+ serial = broadway_output_grab_pointer (broadway_display->output,
+ impl->id, owner_events, time_);
+ reply = _gdk_broadway_display_block_for_input (display, 'g', serial, FALSE);
+ if (reply != NULL)
+ {
+ char *p;
+ char cmd;
+ guint32 reply_serial;
+ int res;
+
+ p = reply;
+
+ cmd = *p++;
+ reply_serial = (guint32)strtol(p, &p, 10);
+ p++; /* Skip , */
+
+ res = strtol(p, &p, 10);
+
+ return res;
+ }
+ }
+
+ return GDK_GRAB_NOT_VIEWABLE;
+ }
}
+#define TIME_IS_LATER(time1, time2) \
+ ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) || \
+ (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 )) \
+ )
+
static void
gdk_broadway_device_ungrab (GdkDevice *device,
guint32 time_)
{
+ GdkDisplay *display;
+ GdkBroadwayDisplay *broadway_display;
+ GdkDeviceGrabInfo *grab;
+ guint32 serial;
+
+ display = gdk_device_get_display (device);
+ broadway_display = GDK_BROADWAY_DISPLAY (display);
+
+ if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
+ {
+ /* Device is a keyboard */
+ }
+ else
+ {
+ /* Device is a pointer */
+
+ if (broadway_display->output)
+ {
+ serial = broadway_output_ungrab_pointer (broadway_display->output, time_);
+
+ gdk_display_flush (display);
+
+ grab = _gdk_display_get_last_device_grab (display, device);
+ if (grab &&
+ (time_ == GDK_CURRENT_TIME ||
+ grab->time == GDK_CURRENT_TIME ||
+ !TIME_IS_LATER (grab->time, time_)))
+ grab->serial_end = serial;
+ }
+ }
}
static GdkWindow *
GdkScreen *screen;
GdkWindow *root, *window;
char *p;
- int button, dir,key;
+ int button, dir, key, detail;
guint32 serial;
guint64 time;
GdkEvent *event = NULL;
switch (cmd) {
case 'e': /* Enter */
p = parse_pointer_data (p, &data);
+ p++; /* Skip , */
+ detail = strtol(p, &p, 10);
display_broadway->last_x = data.root_x;
display_broadway->last_y = data.root_y;
event->crossing.y = data.win_y;
event->crossing.x_root = data.root_x;
event->crossing.y_root = data.root_y;
- event->crossing.mode = GDK_CROSSING_NORMAL;
+ event->crossing.mode = detail;
event->crossing.detail = GDK_NOTIFY_ANCESTOR;
gdk_event_set_device (event, display->core_pointer);
break;
case 'l': /* Leave */
p = parse_pointer_data (p, &data);
+ p++; /* Skip , */
+ detail = strtol(p, &p, 10);
display_broadway->last_x = data.root_x;
display_broadway->last_y = data.root_y;
event->crossing.x_root = data.root_x;
event->crossing.y_root = data.root_y;
event->crossing.mode = GDK_CROSSING_NORMAL;
- event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+ event->crossing.detail = detail;
gdk_event_set_device (event, display->core_pointer);
node = _gdk_event_queue_append (display, event);
}
break;
+ case 'g':
+ case 'u':
+ _gdk_display_device_grab_update (display, display->core_pointer, NULL, serial);
+ break;
case 'q':
g_printerr ("Got unexpected query pointer reply w serial %d\n", serial);
break;